home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / STUTTGART / LANG / C / LIB / UNIXLIB37B / !UnixLib37 / src / unix / c / uname < prev    next >
Text File  |  1996-11-09  |  9KB  |  419 lines

  1. /****************************************************************************
  2.  *
  3.  * $Source: /unixb/home/unixlib/source/unixlib37/src/unix/c/RCS/uname,v $
  4.  * $Date: 1996/10/30 22:04:51 $
  5.  * $Revision: 1.2 $
  6.  * $State: Rel $
  7.  * $Author: unixlib $
  8.  *
  9.  * $Log: uname,v $
  10.  * Revision 1.2  1996/10/30 22:04:51  unixlib
  11.  * Massive changes made by Nick Burret and Peter Burwood.
  12.  *
  13.  * Revision 1.1  1996/04/19 21:35:27  simon
  14.  * Initial revision
  15.  *
  16.  ***************************************************************************/
  17.  
  18. static const char rcs_id[] = "$Id: uname,v 1.2 1996/10/30 22:04:51 unixlib Rel $";
  19.  
  20. #include <ctype.h>
  21. #include <string.h>
  22. #include <stdlib.h>
  23. #include <unistd.h>
  24.  
  25. #include <sys/unix.h>
  26. #include <sys/param.h>
  27. #include <sys/os.h>
  28.  
  29. /* I know this is fucking incomprehensible code - it's fast. ;-) */
  30.  
  31. /* This bit map controls how uname processes filenames
  32.  * 0 : 1 => No processing done at all
  33.  * 1 : 0 => Truncate each path element at 10 chars, 1 => max length is 55 chars
  34.  (for the longfiles module)
  35.  * 2 : 1 => If path element is too long, drop vowels before truncating
  36.  */
  37.  
  38. int __uname_control = __UNAME_DROP_VOWEL + __UNAME_LONG_TRUNC;
  39.  
  40. static char *__unbuf;        /* the name buffer */
  41.  
  42. /* __sdirseg(s1,&s2) checks s1 to see if it is a special directory name
  43.  * if it is, it copies the translation into s2, returning the next segment
  44.  * if not, it returns 0 */
  45.  
  46. static char *
  47. __sdirseg (register char *s1, char **s2_)
  48. {
  49.   register char *s2 = *s2_, *s3, *s4;
  50.   register int i, j;
  51.  
  52.   for (j = 0; j < MAXSDIR; j++)
  53.     {
  54.       if (!(s3 = __sdir[j].name))
  55.     break;
  56.       s3--, s4 = s1 - 1;
  57.       while (++s4, ((i = *++s3) && i == *s4));
  58.       if (!i && (!(i = *s4) || i == '/'))
  59.     {
  60.       s3 = __sdir[j].riscos_name;
  61.       while (*s2++ = *s3++);
  62.       s2--;
  63.       *s2_ = s2;
  64.       return (s4);
  65.     }
  66.     }
  67.   return (0);
  68. }
  69.  
  70. /* __sfixseg(s1) returns -1 if s1 is a special suffix, 0 if not */
  71.  
  72. static int
  73. __sfixseg (register char *s1)
  74. {
  75.   register char *s3, *s4;
  76.   register int i, j;
  77.  
  78.   for (j = 0; j < MAXSFIX; j++)
  79.     {
  80.       if (!(s3 = __sfix[j]))
  81.     break;
  82.       s3--, s4 = s1 - 1;
  83.       while (++s4, ((i = *++s3) && i == *s4));
  84.       if (!i && (!(i = *s4) || i == '/'))
  85.     return (-1);
  86.     }
  87.   return (0);
  88. }
  89.  
  90. #define UNAME_MAXNAMLEN       10
  91. #define LONG_MAXNAMLEN       55
  92.  
  93. char *
  94. __uname (char *name, int cflag)
  95. {
  96.   static char *_name;
  97.   register char *s1, *s2, *e1, *e2;
  98.   register int h, i, j, k;
  99.   int r[6];
  100.   char *s2_[1];
  101.   int maxnamlen;
  102.  
  103.   if (!name)
  104.     return ("");
  105.  
  106.   if (!__unbuf)
  107.     if (!(__unbuf = malloc (MAXPATHLEN << 1)))
  108.       return (0);
  109.  
  110.   _name = (_name == __unbuf) ? (__unbuf + MAXPATHLEN) : __unbuf;
  111.   if (__uname_control & __UNAME_NO_PROCESS)
  112.     {
  113.       return (strcpy (_name, name));
  114.     }
  115.  
  116.   s1 = name;
  117.   s2 = _name;
  118.  
  119.   if (!(k = *s1))
  120.     {
  121.       *s2++ = 0;
  122.       return (_name);
  123.     }
  124.  
  125.   maxnamlen = (__uname_control & __UNAME_LONG_TRUNC) ? LONG_MAXNAMLEN : UNAME_MAXNAMLEN;
  126.  
  127.   /* Process the filename.
  128.      Check the first character of the filename for a '/'.  If found,
  129.      move pointer on one byte.
  130.  
  131.      Get the value of the byte.  */
  132.  
  133.   if (k == '/')
  134.     i = *++s1;
  135.   else
  136.     i = k;
  137.  
  138.   /* h points one character on from i.  */
  139.   h = s1[1];
  140.  
  141.   /* Case1: Special characters in 'i': $ @ % ^ & and frontslash.  */
  142.   if (i == '$' || i == '@' || i == '%' || i == '^' || i == '&' || i == '\\')
  143.     {
  144.       /* Copy characters from s1 to s2 until we hit a '/'.  */
  145.       while ((j = *s1++) && j != '/')
  146.     *s2++ = j;
  147.       /* We used post indexed addressing which has gone one character too far.  */
  148.       s1--;
  149.       i = j;
  150.       k = '.';
  151.       /* Since we have done the above then there is not the existance
  152.          of special fields in this filename e.g. /dev, /usr and /var.
  153.          So branch past these checks.  */
  154.       goto main;
  155.     }
  156.  
  157.   /* Case 2: a ':' with a character after it but reject
  158.      sequences :. and ::  */
  159.   if (i == ':' && h && h != '.' && h != ':')
  160.     {
  161.       /* Copy the : and the character after to the destination string.
  162.          Copy any further characters up to the next '/'.  */
  163.       *s2++ = ':';
  164.       *s2++ = h;
  165.       s1 += 2;
  166.       while ((j = *s1++) && j != '/')
  167.     *s2++ = j;
  168.       /* We used post indexed addressing which has gone one character too far.  */
  169.       s1--;
  170.       i = j;
  171.       k = '.';
  172.       /* Since we have done the above then there is not the existance
  173.          of special fields in this filename e.g. /dev, /usr and /var.
  174.          So branch past these checks.  */
  175.       goto main;
  176.     }
  177.  
  178.   /* Case 3: two consecutive characters but not a colon as the first i.e.
  179.      the format abc:  */
  180.   if (i && i != ':' && h)
  181.     {
  182.       e1 = s1;
  183.       /* Increment e1 until we reach a / . or : */
  184.       while ((j = *++e1) && j != '/' && j != '.' && j != ':');
  185.       if (j == ':')
  186.     {
  187.       /* We've come across a colon. Copy the characters just passed up
  188.          to the colon into the destination string.  */
  189.       /* we know its of the format abc: Now see if its an FS spec or path spec */
  190.       e1++;
  191.       while ((*s2++ = *s1), ++s1 < e1)
  192.         continue;
  193.       if (e1[0] == ':' || e1[0] == '/')
  194.         {
  195.           /* Copy into the destination string any characters up to the
  196.              next '/' */
  197.           while ((j = *s1++) && j != '/')
  198.         *s2++ = j;
  199.           /* We used post indexed addressing which has gone
  200.              one character too far.  */
  201.           s1--;
  202.           i = j;
  203.           k = (s1 == e1) ? 0 : '.';
  204.         }
  205.       else
  206.         {
  207.           /* A path spec.  */
  208.           i = j = '/';
  209.           k = 0;
  210.           s1--;
  211.         }
  212.       /* Skip special first field checking.  */
  213.       goto main;
  214.     }
  215.     }
  216.  
  217.   /* Case 4: The path name does not start with a '/'.  */
  218.   if (k != '/')
  219.     {
  220.       /* If it starts with a dot and the next character is either
  221.          non existant or a '/' then we must be specifing the
  222.          currently selected directory.  */
  223.       if (i == '.' && (!h || h == '/'))
  224.     {
  225.       *s2++ = '@';
  226.       s1 += 1;
  227.       i = h;
  228.       k = '.';
  229.     }
  230.       else
  231.     k = 0;
  232.       goto main;
  233.     }
  234.  
  235.   /* dev/ */
  236.   if (i == 'd' && h == 'e' && s1[2] == 'v' && s1[3] == '/')
  237.     {
  238.       /* Copy to the destination string as dev:  */
  239.       s1 += 4;
  240.       while (*s2++ = *s1++);
  241.       s2[-1] = ':';
  242.       s2[0] = 0;
  243.       return (_name);
  244.     }
  245.  
  246.   /* usr/ */
  247.   if (i == 'u' && h == 's' && s1[2] == 'r' && s1[3] == '/' &&
  248.       (*s2_ = s2, e1 = __sdirseg (s1 + 4, s2_)))
  249.     {
  250.       /* Copy in a path name relevant to usr/ */
  251.       s1 = e1;
  252.       s2 = *s2_;
  253.       i = *s1;
  254.       k = '.';
  255.       goto main;
  256.     }
  257.  
  258.   /* var/ */
  259.   if (i == 'v' && h == 'a' && s1[2] == 'r' && s1[3] == '/' &&
  260.       (*s2_ = s2, e1 = __sdirseg (s1 + 4, s2_)))
  261.     {
  262.       /* Copy in a path name relevant to var/ */
  263.       s1 = e1;
  264.       s2 = *s2_;
  265.       i = *s1;
  266.       k = '.';
  267.       goto main;
  268.     }
  269.  
  270.   if (*s2_ = s2, e1 = __sdirseg (s1, s2_))
  271.     {
  272.       s1 = e1;
  273.       s2 = *s2_;
  274.       i = *s1;
  275.       k = '.';
  276.       goto main;
  277.     }
  278.  
  279.   /* Finally we must have started with a '/' so add a '$' to
  280.      the start of the destination string.  */
  281.   *s2++ = '$';
  282.   k = '.';
  283.  
  284. main:
  285.  
  286.   if (i == '/')
  287.     {
  288.       /* Search through string until we have passed all '/'s */
  289.       while ((i = *++s1) == '/');
  290.       h = s1[1];
  291.     }
  292.  
  293.   if (i && k)
  294.     *s2++ = k;
  295.  
  296.   if (i)
  297.     for (;;)
  298.       {
  299.     /* Do nothing with ./ */
  300.     if (i == '.' && (h == '/' || !h))
  301.       {
  302.         --s2;
  303.         s1 += 1;
  304.         goto loop;
  305.       }
  306.  
  307.     /* Convert ../ to the RISC OS up directory '^'. */
  308.     if (i == '.' && h == '.' && ((j = s1[2]) == '/' || !j))
  309.       {
  310.         *s2++ = '^';
  311.         s1 += 2;
  312.         goto loop;
  313.       }
  314.  
  315.     /* A redirection operator < */
  316.     if (i == '<' && h)
  317.       {
  318.         e1 = s1;
  319.         while ((j = *++e1) && j != '>');
  320.         if (j == '>')
  321.           {
  322.         while ((*s2++ = *s1), ++s1 <= e1);
  323.         while ((j = *s1++) && j && j != '/')
  324.           *s2++ = j;
  325.         s1--;
  326.         goto loop;
  327.           }
  328.       }
  329.  
  330.     e1 = s1;
  331.     while ((i = *++e1) && i != '/' && i != '.');
  332.  
  333.     if (i == '.')
  334.       {
  335.         e2 = e1;
  336.         while ((j = *++e2) && j != '/')
  337.           if (j == '.')
  338.         e1 = e2;
  339.         if (e2 > ++e1 && __sfixseg (e1))
  340.           {
  341.         k = e2 - e1;
  342.         while ((*s2++ = *e1), ++e1 < e2);
  343.         if (cflag)
  344.           {
  345.             *s2 = 0;
  346.             if (!os_file (0x05, _name, r) && !r[0])
  347.               os_file (0x08, _name, r);
  348.           }
  349.         *s2++ = '.';
  350.         e1 -= k + 1;
  351.           }
  352.         else
  353.           {
  354.         register char *e3;
  355.  
  356.         e1--;
  357.         e3 = s1;
  358.         while ((*s2++ = *e3), ++e3 < e1);
  359.         *s2 = 0;
  360.         s2 -= (e1 - s1);
  361.         if (!os_file (0x05, _name, r) && r[0] == 2)
  362.           {
  363.             while ((j = *s1++) && j != '/')
  364.               *s2++ = j;
  365.             s1--;
  366.             goto loop;
  367.           }
  368.         e1 = e2;
  369.           }
  370.       }
  371.     else
  372.       e2 = e1;
  373.  
  374.     i = maxnamlen;
  375.     j = (e1 - s1) - i;
  376.     while (s1 < e1 && i)
  377.       {
  378.         k = *s1++;
  379.         /* Replace dots with backslashes.  */
  380.         if (k == '.')
  381.           k = '/';
  382.         /* Replace @ $ % ^ & : " which are illegal characters in RISC OS
  383.            filenames with an underscore.  */
  384.         else if (k == '@' || k == '$' || k == '%' || k == '^' || \
  385.              k == '&' || k == ':' || k == '"' || !isgraph (k))
  386.           k = '_';
  387.         /* || k == '*' || k == '#' ? */
  388.         /* If requested remove vowels from the filename.  */
  389.         if (((__uname_control & __UNAME_DROP_VOWEL) == __UNAME_DROP_VOWEL) && j > 0 && i < maxnamlen)
  390.           if (k == 'a' || k == 'e' || k == 'i' || k == 'o' || k == 'u')
  391.         {
  392.           j--;
  393.           continue;
  394.         }
  395.         *s2++ = k;
  396.         i--;
  397.       }
  398.     s1 = e2;
  399.  
  400.       loop:
  401.  
  402.     if ((i = *s1) == '/')
  403.       while ((i = *++s1) == '/');
  404.  
  405.     if (!i || (s2 - _name) > (MAXPATHLEN - maxnamlen - 2))
  406.       break;
  407.  
  408.     h = s1[1];
  409.     *s2++ = '.';
  410.       }
  411.  
  412.   if ((s2 - _name) <= MAXPATHLEN)
  413.     *s2 = 0;
  414.   else
  415.     _name[MAXPATHLEN - 1] = 0;
  416.  
  417.   return (_name);
  418. }
  419.